﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThreadNote
{

    /// <summary>
    /// 将Asynchronous Programming Model[这是.NET 历史中第一个异步编程模型]
    /// </summary>
    class Program
    {
        // 声明委托的语法： delegate 返回值 委托类名(传入的参数)
        private delegate string RunOnThreadPool(out int threadId);


        private static void Callback(IAsyncResult iAR)
        {
            Console.WriteLine("开始一个回调...");
            Console.WriteLine($"传入的回调状态:{iAR.AsyncState}");
            Console.WriteLine($"Callback是否为线程中的线程：{Thread.CurrentThread.IsThreadPoolThread}");
            Console.WriteLine($"Callback线程池中工作的线程id:{Thread.CurrentThread.ManagedThreadId}");

        }

        private static string Test(out int threadId)
        {
            Console.WriteLine("开始....");
            Console.WriteLine($"Test是否为线程中的线程：{Thread.CurrentThread.IsThreadPoolThread}");
            Thread.Sleep(TimeSpan.FromSeconds(5));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return string.Format($"Test线程池工作的线程id是{threadId}");
        }

        // 控制台的入口函数
        static void Main(string[] args)
        {
            int threadId = 0;
            RunOnThreadPool poolDelegate = Test;
            var th = new Thread(() => Test(out threadId));
            th.Start();
            th.Join();
            Console.WriteLine($"线程的Id{threadId}");
            Console.WriteLine("================================================");

            // 说明：1.poolDelegate是一委托变量,调用的是Test方法
            //       2.BeginInvoke用于运行该委托，CallBack是一回调函数。该回调函数会在异步操作完成后会被调用
            //       3.BeginInvoke立即返回结果，当线程池中的工作线程在执行异步操作时，仍允许我们继续其他工作
            IAsyncResult iar = poolDelegate.BeginInvoke(out threadId, Callback, "一个委托的异步调用");
            //iar.AsyncWaitHandle.WaitOne();
            Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaa");
            string result = poolDelegate.EndInvoke(out threadId, iar);

            Console.WriteLine($"线程池工作线程的Id是{threadId}");
            Console.WriteLine("************************************************");
            //Console.WriteLine(result);

            Console.ReadKey();
        }
    }
}
